package com.example.yibu.common.aspect;

import com.example.yibu.common.notation.MyAnnotation;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Arrays;

@Component
@Aspect
@Slf4j
public class MyAnnotationAspect {

    /*
     * 这是一个切入点
     * */
    @Pointcut("@annotation(com.example.yibu.common.notation.MyAnnotation)")
    public void cutMethod(){

    }
    /**
     * 切点之前
     */
    @Before("cutMethod()")  //始终执行，不受业务逻辑异常影响
    public void before(JoinPoint joinPoint) throws Throwable {
        log.info("============ before ==========");
    }

    /**
     * 切点之后
     */
    @After("cutMethod()")  //始终执行，无论业务逻辑是否抛出异常
    public void after() throws Throwable {
        log.info("============ after ==========");
    }

    /**
     * 切点返回内容后
     */
    @AfterReturning("cutMethod()")  //仅在业务逻辑成功时执行
    public void afterReturning() throws Throwable {
        log.info("============ afterReturning ==========");
        // 获取当前请求的HttpServletRequest对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 获取请求路径
        String requestUri = request.getRequestURI();
        System.out.println("Request URI: "  + requestUri);
    }
/*    @AfterReturning(pointcut = "@annotation(myAnnotation)", returning = "result")
    public void afterReturningAdvice(JoinPoint joinPoint, MyAnnotation myAnnotation, Object result) {
        // 获取当前请求的HttpServletRequest对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 获取请求路径
        String requestUri = request.getRequestURI();
        System.out.println("Request URI: " + requestUri);

        // 获取方法签名
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Method: " + methodName);

        // 获取目标对象
        Object target = joinPoint.getTarget();
        System.out.println("Target object: " + target.getClass().getName());

        // 获取方法参数
        Object[] args = joinPoint.getArgs();
        System.out.println("Arguments: " + Arrays.toString(args));

        // 访问自定义注解的属性
        String annotationValue = myAnnotation.someProperty();
        System.out.println("Annotation value: " + annotationValue);

        // 处理返回值
        System.out.println("Result: " + result);
    }*/


    /**
     * 切点抛出异常后
     */
    @AfterThrowing("cutMethod()") //仅在业务逻辑抛出异常时执行
    public void afterThrowing() throws Throwable {
        log.info("============ afterThrowing ==========");
    }


    @Around("cutMethod() && @annotation(myAnnotation)")  //环绕
    public Object around(ProceedingJoinPoint point, MyAnnotation myAnnotation) throws Throwable {
        log.info("============ around1 ==========");
        Object  obj= point.proceed(point.getArgs());
        log.info("============ around2 ==========");
        return obj;
    }



    /*

    @Pointcut("@annotation(com.example.yibu.common.notation.MyAnnotation)")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void before() {
        System.out.println("前置通知...");
    }

    @After("pointCut()")
    public void after() {
        System.out.println("后置通知...");
    }

    @Around("pointCut()")
    public void around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕通知前...");
        point.proceed();
        System.out.println("环绕通知后...");
    }

    */



    /*

    @Before("@annotation(myCustomAnnotation)")
    public void beforeAdvice(JoinPoint joinPoint, MyCustomAnnotation myCustomAnnotation) {
        System.out.println("Before advice executed");
    }

    @AfterReturning(pointcut = "@annotation(myCustomAnnotation)", returning = "result")
    public void afterReturningAdvice(JoinPoint joinPoint, MyCustomAnnotation myCustomAnnotation, Object result) {
        System.out.println("After returning advice executed with result: " + result);
    }

    @After("execution(* com.example.service.*.*(..))")
    public void afterFinallyAdvice(JoinPoint joinPoint) {
        System.out.println("After finally advice executed");
    }

    @AfterThrowing(pointcut = "@annotation(myCustomAnnotation)", throwing = "ex")
    public void afterThrowingAdvice(JoinPoint joinPoint, MyCustomAnnotation myCustomAnnotation, Throwable ex) {
        System.out.println("After throwing advice executed with exception: " + ex.getMessage());
    }

用途：
    获取方法签名：joinPoint.getSignature()
    获取目标对象：joinPoint.getTarget()
    获取方法参数：joinPoint.getArgs()

用途：
    访问注解的属性值：myCustomAnnotation.someProperty()

用途：
    处理返回值：System.out.println("Result: " + result);

环绕通知:
ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行
    */

}

